package ar.com.ford.it.fullEconomics.logic;

import java.sql.Timestamp;
import java.util.Collection;
import java.util.LinkedList;
import ar.com.ford.it.fullEconomics.FullEconomicsPrs;
import ar.com.ford.it.fullEconomics.exception.FullEconomicsException;
import ar.com.ford.it.fullEconomics.persistence.dao.SupplierDao;
import ar.com.ford.it.fullEconomics.persistence.dto.Teesg01Plant;
import ar.com.ford.it.fullEconomics.persistence.dto.Teess01Supplier;
import ar.com.ford.it.fullEconomics.persistence.dto.Teesx03Intflog;
import ar.com.ford.it.fullEconomics.persistence.dto.Teesx04Intflevent;
import ar.com.ford.it.fullEconomics.struct.CounterStruct;
import ar.com.ford.it.fullEconomics.struct.OptionCombo;
import ar.com.ford.it.fullEconomics.wslx.FullEconomicsWslxUser;
import ar.com.ford.it.webengine.persistence.PersistenceUtil;
import com.ford.it.logging.ILogger;
import com.ford.it.logging.Level;
import com.ford.it.logging.LogFactory;
import com.ford.it.persistence.PersistenceException;

public class SupplierLogic {
    private static final String CLASS_NAME = SupplierLogic.class.getName();
    private static final ILogger log = LogFactory.getInstance().getLogger(
            CLASS_NAME);

    /**
     * Busca Supplier seg�n code y name para la planta "plant".
     * 
     * @param code
     * @param name
     * @param plant
     * @return Supplier que se correspondan con la b�squeda. Si code y name
     * son vac�os, entonces busca todos los Supplier
     * @throws FullEconomicsException
     */
    public Collection<Teess01Supplier> findSupplier(String classCode,
                                                    String code, String name,
                                                    Teesg01Plant plant)
            throws FullEconomicsException {

        String METHOD_NAME = "findSupplier";
        log.entering(CLASS_NAME, METHOD_NAME);
        SupplierDao dao = new SupplierDao();
        Teess01Supplier supplier = new Teess01Supplier();
        Collection<Teess01Supplier> ret = null;
        supplier.setEess01PlantCodeC(plant);
        supplier.setEess01SupplierNameN(name);
        supplier.setEess01SupplierCodeC(code);
        supplier.setEess01SupplierClassCodeC(classCode);
        try {
            ret = dao.findSupplier(supplier);
        } catch (PersistenceException e) {
            log.logp(Level.SEVERE, CLASS_NAME, METHOD_NAME, "findSupplier", e);
            throw new FullEconomicsException(e,
                    FullEconomicsPrs.MessageErrors.Supplier.FIND);
        }
        log.exiting(CLASS_NAME, METHOD_NAME);
        return ret;
    }

    /**
     * Crea Supplier
     * 
     * @param supplier
     * @param user
     * @throws FullEconomicsException
     */
    public void createSupplier(Teess01Supplier supplier,
                               FullEconomicsWslxUser user)
            throws FullEconomicsException {
        String METHOD_NAME = "createSupplier";
        log.entering(CLASS_NAME, METHOD_NAME);
        SupplierDao dao = new SupplierDao();

        try {
            PersistenceUtil.newTransaction();
            supplier.setEess01CreateUserC(user.getId());
            supplier.setEess01LastUpdtUserC(user.getId());
            supplier.setEess01PlantCodeC(user.getTeesg01Plant());
            supplier
                    .setEess01CreateS(new Timestamp(System.currentTimeMillis()));
            supplier.setEess01LastUpdtS(new Timestamp(System
                    .currentTimeMillis()));

            dao.createSupplier(supplier);
            PersistenceUtil.commitTransaction();
        } catch (PersistenceException e) {
            log
                    .logp(Level.SEVERE, CLASS_NAME, METHOD_NAME,
                            "createSupplier", e);
            throw new FullEconomicsException(e,
                    FullEconomicsPrs.MessageErrors.Supplier.CREATE);
        }
        log.exiting(CLASS_NAME, METHOD_NAME);

    }

    public void updateSupplier(Teess01Supplier supplier,
                               FullEconomicsWslxUser user)
            throws FullEconomicsException {

        String METHOD_NAME = "updateSupplier";
        log.entering(CLASS_NAME, METHOD_NAME);
        Teess01Supplier workingCopy = new Teess01Supplier();
        SupplierDao dao = new SupplierDao();
        try {
            PersistenceUtil.newTransaction();
            PersistenceUtil.getPersistenceManager().clearCache();
            workingCopy = dao.getUpdateSupplier(supplier);
            workingCopy.setEess01LastUpdtUserC(user.getId());
            workingCopy.setEess01LastUpdtS(new Timestamp(System
                    .currentTimeMillis()));
            workingCopy.setEess01SupplierNameN(supplier
                    .getEess01SupplierNameN());
            PersistenceUtil.commitTransaction();
        } catch (PersistenceException e) {
            log.logp(Level.SEVERE, CLASS_NAME, METHOD_NAME, "update Supplier",
                    e);
            throw new FullEconomicsException(e,
                    FullEconomicsPrs.MessageErrors.Supplier.UPDATE);
        }
        log.exiting(CLASS_NAME, METHOD_NAME);
    }

    /**
     * Elimina un supplier
     * 
     * @param supplier
     * @throws FullEconomicsException
     */
    public void deleteSupplier(Teess01Supplier supplier)
            throws FullEconomicsException {
        String METHOD_NAME = "deleteSupplier";
        log.entering(CLASS_NAME, METHOD_NAME);
        SupplierDao dao = new SupplierDao();
        try {
            PersistenceUtil.newTransaction();
            dao.deleteSupplier(supplier);
            PersistenceUtil.commitTransaction();
        } catch (PersistenceException e) {
            log
                    .logp(Level.SEVERE, CLASS_NAME, METHOD_NAME,
                            "deleteSupplier", e);
            throw new FullEconomicsException(e,
                    FullEconomicsPrs.MessageErrors.Supplier.DELETE);
        }
        log.exiting(CLASS_NAME, METHOD_NAME);
    }

    /**
     * Pregunta si es un unico resultado
     * 
     * @param name
     * @param plant
     * @return boolean
     * @throws FullEconomicsException
     */
    public boolean supplierNameAlreadyExists(String name, Teesg01Plant plant)
            throws FullEconomicsException {
        String METHOD_NAME = "supplierNameAlreadyExists";
        log.entering(CLASS_NAME, METHOD_NAME);
        SupplierDao dao = new SupplierDao();
        Teess01Supplier supplier = new Teess01Supplier();
        supplier.setEess01PlantCodeC(plant);
        supplier.setEess01SupplierNameN(name);
        boolean ret;

        try {
            ret = dao.supplierNameAlreadyExists(supplier);
        } catch (PersistenceException e) {
            log.logp(Level.SEVERE, CLASS_NAME, METHOD_NAME,
                    "supplierNameAlreadyExists", e);
            throw new FullEconomicsException(e,
                    FullEconomicsPrs.MessageErrors.Supplier.FIND);
        }
        log.exiting(CLASS_NAME, METHOD_NAME);
        return ret;
    }

    /**
     * 
     * @return Colecci�n de posibles Supplier Types
     */
    public Collection<OptionCombo> getComboSupplierType() {
        LinkedList<OptionCombo> list = new LinkedList<OptionCombo>();

        // XXX Ver como internacionalizar este combo
        list.add(new OptionCombo("C", "Custom"));
        list.add(new OptionCombo("F", "Ford"));
        return list;
    }

    public Teess01Supplier getSupplierByPk(Teess01Supplier supplier)
            throws FullEconomicsException {
        String METHOD_NAME = "getSupplierByPk";
        log.entering(CLASS_NAME, METHOD_NAME);
        SupplierDao dao = new SupplierDao();

        try {
            return (Teess01Supplier) dao.getObjById(supplier);
        } catch (PersistenceException e) {
            log.logp(Level.SEVERE, CLASS_NAME, METHOD_NAME, "getSupplierByPk",
                    e);
            throw new FullEconomicsException(e,
                    FullEconomicsPrs.MessageErrors.Supplier.GET);
        }
    }

    public CounterStruct mergeSuppliers(Collection<Teess01Supplier> suppliers,
                                 String userId, Teesx03Intflog logNumber)
            throws FullEconomicsException {

        String METHOD_NAME = "mergeSupplier";
        log.entering(CLASS_NAME, METHOD_NAME);
        Teess01Supplier workingCopy = new Teess01Supplier();
        SupplierDao dao = new SupplierDao();
        LogProcessLogic logLogic = new LogProcessLogic();
        int countLine = 0;
        CounterStruct counter = new CounterStruct();
        try {

            for (Teess01Supplier supplier : suppliers) {
                PersistenceUtil.newTransaction();
                PersistenceUtil.getPersistenceManager().clearCache();
                countLine++;
                workingCopy = dao.getUpdateSupplier(supplier);
                if (workingCopy != null) {
                    workingCopy.setEess01LastUpdtUserC(userId);
                    workingCopy.setEess01LastUpdtS(new Timestamp(System
                            .currentTimeMillis()));
                    if (!workingCopy.getEess01SupplierNameN().equalsIgnoreCase(
                            supplier.getEess01SupplierNameN())) {
                        logLogic.insertLogIntfLevent(userId, logNumber, "U",
                                this
                                        .getUpdateDescription(workingCopy,
                                                supplier), countLine);
                        workingCopy.setEess01SupplierNameN(supplier
                                .getEess01SupplierNameN());
                        workingCopy.setTeesx03Intflog(logNumber);
                        counter.addCount();
                    }
                } else {
                    supplier.setTeesx03Intflog(logNumber);
                    FullEconomicsWslxUser user = new FullEconomicsWslxUser(
                            userId);
                    user.setTeesg01Plant(supplier.getEess01PlantCodeC());
                    createSupplier(supplier, user);
                    counter.addCount();
                }
                PersistenceUtil.commitTransaction();
            }

        } catch (PersistenceException e) {
            logLogic.insertLogIntfLevent(userId, logNumber, "E",
                    "Internal error. Proccess canceled", countLine);
            counter.addError();
            try {
                this.bmRollBack(logNumber, userId);
            } catch (PersistenceException e1) {
                logLogic.insertLogIntfLevent(userId, logNumber, "E",
                        "RollBack error", countLine);
                counter.addError();
            }
            log.logp(Level.SEVERE, CLASS_NAME, METHOD_NAME, "update Supplier",
                    e);
            throw new FullEconomicsException(e,
                    FullEconomicsPrs.MessageErrors.Supplier.UPDATE);
        }
        log.exiting(CLASS_NAME, METHOD_NAME);
        return counter;

    }

    private String getUpdateDescription(Teess01Supplier origSupplier,
                                        Teess01Supplier newSupplier) {
        String desc = "Proveedor modificado: Codigo=F-"
                + origSupplier.getEess01SupplierCodeC() + "; Planta="
                + origSupplier.getEess01PlantCodeC().getEesg01PlantCodeC()
                + ". Se cambio: Nombre="
                + origSupplier.getEess01SupplierNameN() + " por "
                + newSupplier.getEess01SupplierNameN();
        return desc;
    }

    private Teess01Supplier getOrigSupplier(Teesx04Intflevent event) {
        Teess01Supplier supplier = new Teess01Supplier();
        Teesg01Plant plant = new Teesg01Plant();
        String desc = event.getEesx04IevntMessageDescripX();
        int codeIndex = desc.indexOf("Codigo");
        int plantIndex = desc.indexOf("Planta");
        int endPlantIndex = desc.indexOf(". Se cambio");
        int nameIndex = desc.indexOf("Nombre");
        int endNameIndex = desc.indexOf(" por ", nameIndex);

        String code = desc.substring(codeIndex + 9, plantIndex - 2);
        String plantCode = desc.substring(plantIndex + 7, endPlantIndex);
        String name = desc.substring(nameIndex + 7, endNameIndex);

        plant.setEesg01PlantCodeC(plantCode);
        supplier.setEess01SupplierCodeC(code);
        supplier.setEess01SupplierClassCodeC("F");
        supplier.setEess01SupplierNameN(name);
        supplier.setEess01PlantCodeC(plant);

        return supplier;
    }
    
    private void bmRollBack(Teesx03Intflog logNumber, String userId)throws PersistenceException, FullEconomicsException {
        SupplierDao dao = new SupplierDao();
        String[] fields = { "teesx03Intflog" };
        Object[] values = { logNumber };
        String[] eventFields = { "teesx03Intflog", "eesx04IevntTypeCodeC" };
        Object[] eventValues = { logNumber, "U" };
        
        
        //busco las modificaciones y las vuelvo atras
        Collection<Teesx04Intflevent> modifs = dao.findAll(new Teesx04Intflevent(), eventFields, eventValues);
        for(Teesx04Intflevent event : modifs){
            Teess01Supplier supplier = this.getOrigSupplier(event);
            FullEconomicsWslxUser user = new FullEconomicsWslxUser(userId);
            user.setTeesg01Plant(supplier.getEess01PlantCodeC());
            this.updateSupplier(supplier, user);
        }
        
        //borro los suppliers creados
        Collection<Teess01Supplier> suppliers = dao.findAll(new Teess01Supplier(), fields, values);
        for(Teess01Supplier supplier : suppliers)
            this.deleteSupplier(supplier);
        
    }
}
